#include <iostream>
using namespace std;
#include <sys/types.h>
#include <sys/socket.h>
#include <cstring>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
#include <json-c/json.h>
#include "stdShared.h"

#include <pthread.h>
/* 服务端口 */
#define SERVER_PORT 8080

/* 缓冲区的大小 */
#define BUFFER_SIZE 128

#define SIZE 20
struct userInfo
{
    int type;
    char name[SIZE];
    char passwd[SIZE];
};

void *thread_func(void *arg)
{
    /* 线程分离 */
    pthread_detach(pthread_self());
    /* 参数转换 */
    int connfd = *(int *)arg;
    /* 接收缓冲区 */
    char readBuffer[BUFFER_SIZE];
    /* 清空缓冲区 */
    memset(readBuffer, 0, sizeof(readBuffer));

    int readBytes = 0;
    while (1)
    {

        memset(readBuffer, 0, sizeof(readBuffer));
        readBytes = read(connfd, readBuffer, sizeof(readBuffer));
        if (readBytes < 0)
        {
            perror("read error:");
            break;
        }
        else if (readBytes == 0)
        {
            cout << "客户端下线" << endl;
            break;
        }
        // cout << "readBytes:" << readBytes << " readBuffer:" << readBuffer << endl;

        /* 1.将json字符串解析成字符串 */
        json_object *jsonObj = json_tokener_parse(readBuffer);

        /* 2.根据key得到value. */
#if 0
        json_object *typeVal = json_object_object_get(jsonObj, "type");
        cout << "type:" << json_object_get_int(typeVal);
#else
        int type = json_object_get_int(json_object_object_get(jsonObj, "type"));
        // const char *name = json_object_get_string(json_object_object_get(jsonObj, "name"));
        // const char *passwd = json_object_get_string(json_object_object_get(jsonObj, "passwd"));
        const char *musicname = json_object_get_string(json_object_object_get(jsonObj, "musicname"));

        if (type == REGISTER)
        {
            cout << "用户已存在，请勿重复注册" << endl;

            cout << "注册中..." << endl;
            // cout << "name:" << name << endl;
            // cout << "passwd:" << passwd << endl;
        }
        else if (type == LOGIN)
        {
            cout << "登陆中..." << endl;
            // cout << "name:" << name << endl;
            // cout << "passwd:" << passwd << endl;
        }
        else if (type == DOWNLOAD)
        {
            cout << "下载中..." << endl;
            cout << musicname << endl;
        }
        /* 释放json对象 */
        json_object_put(jsonObj);
#endif
    }

    /* 回收文件描述符 */
    close(connfd);
    /* 线程退出 */
    pthread_exit(NULL);
}

int main()
{
    /* 创建socket套接字 */
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd == -1)
    {
        perror("socket error:");
        exit(-1);
    }
    // cout << "sockfd:" << sockfd << endl;

    /* 设置端口复用 */
    int optVal = 1;
    setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &optVal, sizeof(optVal));

    /* 绑定Ip和端口信息 */
    struct sockaddr_in localAddress;
    /* 清空结构体脏数据 */
    memset(&localAddress, 0, sizeof(localAddress));
    /* 地址族是IPV4 */
    localAddress.sin_family = AF_INET;
    localAddress.sin_port = htons(SERVER_PORT);
    /* 设置全通规则 */
    localAddress.sin_addr.s_addr = htonl(INADDR_ANY);
    bind(sockfd, reinterpret_cast<const struct sockaddr *>(&localAddress), sizeof(localAddress));

    /* 设置监听 */
    listen(sockfd, 10);
    cout << "服务器阻塞等待客户端接入..." << endl;

    /* 通信句柄 */
    /* 阻塞函数 */
    while (1)
    {
        int connfd = accept(sockfd, NULL, NULL);
        cout << "有人跟我连接了..." << connfd << endl;

#if 0
    userInfo info;
    while (1)
    {
        memset(&info, 0, sizeof(info));

        readBytes = read(connfd, &info, sizeof(info));
        cout << "type:" << info.type << ",name:" << info.name << ",passwd:" << info.passwd << endl;
#endif

#if 0
        readBytes = read(connfd, readBuffer, sizeof(readBuffer));

        cout << "readBytes:" << readBytes << ", readBuffer:" << readBuffer << endl;

        for (int idx = 0; idx < readBytes; idx++)
        {
            readBuffer[idx] = toupper(readBuffer[idx]);
        }

        /* 写回客户端 */
        write(connfd, readBuffer, readBytes);
}
#endif

        pthread_t tid;
        int ret = pthread_create(&tid, NULL, thread_func, &connfd);
        if (ret != 0)
        {
            perror("thread create error:");
            exit(-1);
        }

        sleep(1);
    }

    return 0;
}